#include "udp_server.h"
#include <stdio.h>
#include <errno.h>
#include "hilog.h"

UdpServer::UdpServer()
{
    serverfd_ = 0;    
    is_run_ = false;
    memset(buf_, 0, MAX_UDP_LEN);
}

UdpServer::~UdpServer()
{

}

int UdpServer::start_service(int port)
{
  //创建套接口
  if ((serverfd_ = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  {
     hi_error("udp server socket create failed err=%d", errno);
     return -1;
  }

  //对套接字初始化
  bzero(&addr_, sizeof(addr_));
  addr_.sin_family = AF_INET;
  addr_.sin_port = htons(port);
  addr_.sin_addr.s_addr = htonl(INADDR_ANY);


  //设置端口
  if (bind(serverfd_, (struct sockaddr*)&addr_, sizeof(addr_)) < 0)
  {
      hi_error("udp server bind failed err=%d", errno);
      close(serverfd_);
      return -1;
  }

  hi_trace("start udp server at port %d", port);
  is_run_ = true;
  start("udp server thread");
  return 0;
}

int UdpServer::stop_service()
{
    is_run_ = false;
    stop_thread();
    if(serverfd_ > 0) {
        close(serverfd_);
    }
}

void UdpServer::process()
{
    while (is_run_)
    {     
        FD_ZERO(&rset_);  
        FD_SET(serverfd_, &rset_);
        struct timeval timeout={3,0};       
        int ret = select(serverfd_+1, &rset_, NULL, NULL, &timeout);       
        switch (ret) {
        case -1:
            // if(errno == EINTR) continue;
            hi_error("select err=%d\n", errno);
            break;
        case 0:
            //3秒超时 printf("select timeout...\n");
            FD_CLR(serverfd_, &rset_);        
            break;

        default:
            if (FD_ISSET(serverfd_, &rset_))
            {
               struct sockaddr_in addr;              
               socklen_t addrlen = sizeof(addr);
               bzero(&addr, sizeof(addr));
               memset(buf_, 0, MAX_UDP_LEN);               
               int bytes = recvfrom(serverfd_, buf_, MAX_UDP_LEN, 0 , (struct sockaddr*)&addr, &addrlen);
               if(bytes > 0) {   
                   char ipbuf[16] = "";               
                   hi_trace("recv udp buf:%s len: %d from %s", buf_, bytes, inet_ntop(AF_INET, &addr.sin_addr, ipbuf, sizeof(ipbuf)));
                   on_udp_msg(buf_,bytes, ipbuf);
               }
               else {
                   if(errno != 0) {
                       char ipbuf[1024] = "";
                       hi_error("udp server recv data err=%d bytes=%d\n", errno, bytes);
                       hi_error("udp server %s:%s",
                                inet_ntop(AF_INET, &addr.sin_addr, ipbuf, sizeof(ipbuf)), buf_);

                   }
               }
           }
           break;
        }
    }
}
